package utils

import (
	"bytes"
	"crypto/md5"
	"crypto/rand"
	"encoding/base64"
	"encoding/hex"
	"fmt"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/logs"
	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors"
	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
	sms "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms/v20190711"
	"github.com/tencentyun/cos-go-sdk-v5"
	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/transform"
	"io"
	"io/ioutil"
	"math"
	mathRand "math/rand"
	"net/http"
	"net/url"
	"reflect"
	"regexp"
	"strconv"
	"strings"
	"time"
)

type ResJsonStruct struct {
	Status int         `json:"status"`
	Msg    string      `json:"msg"`
	Data   interface{} `json:"data"`
}

// 响应json数据
func ResJson(status int, msg string, data interface{}) *ResJsonStruct {
	return &ResJsonStruct{
		Status: status,
		Msg:    msg,
		Data:   data,
	}
}

// md5字符串比较
func Check(content, encrypted string) bool {
	return strings.EqualFold(Encode(content), encrypted)
}

// md5加密
func Encode(data string) string {
	h := md5.New()
	h.Write([]byte(data))
	return hex.EncodeToString(h.Sum(nil))
}

func UniqueId() string {
	b := make([]byte, 48)
	if _, err := io.ReadFull(rand.Reader, b); err != nil {
		return ""
	}
	return Encode(base64.URLEncoding.EncodeToString(b))
}

// 字符串转int64
func Atoi64(a string) int64 {
	i, _ := strconv.ParseInt(a, 10, 64)
	return i
}

// 字符串转float64
func Atof64(a string) float64 {
	f, _ := strconv.ParseFloat(a, 64)
	return f
}

// 分页结构体
type Paginator struct {
	CurrentPage        int // 当前页码
	TotalCount         int // 总记录条数
	TotalPageCount     int // 总页数
	SymmetricPageCount int // 左右对称页码数
	PerCount           int // 每页显示记录条数
	Total              int // 总页码数
}

func NewPaginator(totalCount int, perCount int, symPageCount int, curPage int) *Paginator {
	totalPageCount := int(math.Ceil(float64(totalCount) / float64(perCount)))
	total := 2*symPageCount + 1
	return &Paginator{
		CurrentPage:        curPage,
		TotalCount:         totalCount,
		TotalPageCount:     totalPageCount,
		SymmetricPageCount: symPageCount,
		PerCount:           perCount,
		Total:              total,
	}
}

// 获取分页页码
func (p *Paginator) GetPageHtml() string {
	if p.TotalPageCount <= 0 {
		return ""
	}
	h := fmt.Sprintf("<span style=\"margin-right:10px;border:none;\">共 %d 页</span>", p.TotalPageCount)
	if p.TotalPageCount == 1 {
		h += fmt.Sprintf("<span style=\"margin-left:10px;border:none;\">共 %d 条数据</span>", p.TotalCount)
		return h
	}
	prePage := p.CurrentPage - 1
	if prePage <= 1 {
		prePage = 1
	}
	nextPage := p.CurrentPage + 1
	if nextPage >= p.TotalPageCount {
		nextPage = p.TotalPageCount
	}
	start := p.CurrentPage - p.SymmetricPageCount
	end := p.CurrentPage + p.SymmetricPageCount
	if p.CurrentPage <= p.SymmetricPageCount {
		start = 1
		end = p.Total
	}
	if p.CurrentPage >= p.TotalPageCount-p.SymmetricPageCount {
		start = p.TotalPageCount - p.Total + 1
		end = p.TotalPageCount
	}
	if p.TotalPageCount <= p.Total {
		start = 1
		end = p.TotalPageCount
	}
	h += fmt.Sprintf("<a class=\"prev\" href=\"javascript:void(0)\" page-num=\"%d\">&lt;&lt;</a>", prePage)
	for i := start; i <= end; i++ {
		if i == p.CurrentPage {
			h += fmt.Sprintf("<span class=\"current\">%d</span>", i)
		} else {
			h += fmt.Sprintf("<a class=\"num\" href=\"javascript:void(0)\" page-num=\"%d\">%d</a>", i, i)
		}
	}
	h += fmt.Sprintf("<a class=\"next\" href=\"javascript:void(0)\" page-num=\"%d\">&gt;&gt;</a>", nextPage)
	h += fmt.Sprintf("<span style=\"margin-left:10px;border:none;\">共 %d 条数据</span>", p.TotalCount)
	return h
}

// 获取腾讯云存储对象API client
func GetStorageObj() *cos.Client {
	bucketDomain := beego.AppConfig.String("bucketdomain")
	secretId := beego.AppConfig.String("secretid")
	secretKey := beego.AppConfig.String("secretkey")
	u, _ := url.Parse(bucketDomain)
	b := &cos.BaseURL{BucketURL: u}
	c := cos.NewClient(b, &http.Client{
		Transport: &cos.AuthorizationTransport{
			SecretID:  secretId,
			SecretKey: secretKey,
		},
	})
	return c
}

func Utf8ToGbk(s []byte) []byte {
	reader := transform.NewReader(bytes.NewReader(s), simplifiedchinese.GBK.NewEncoder())
	d, err := ioutil.ReadAll(reader)
	if err != nil {
		logs.Error("can not convert utf8 to gbk")
		return nil
	}
	return d
}

func GbkToUtf8(s []byte) []byte {
	reader := transform.NewReader(bytes.NewReader(s), simplifiedchinese.GBK.NewDecoder())
	d, err := ioutil.ReadAll(reader)
	if err != nil {
		logs.Error("can not convert gbk to utf8")
		return nil
	}
	return d
}

// 判断某个值是否存在于某个切片中
func IsExistItem(value interface{}, array interface{}) bool {
	switch reflect.TypeOf(array).Kind() {
	case reflect.Slice:
		s := reflect.ValueOf(array)
		for i := 0; i < s.Len(); i++ {
			if reflect.DeepEqual(value, s.Index(i).Interface()) {
				return true
			}
		}
	}
	return false
}

// 判断是否是有效的手机号
func IsMobile(mobile string) bool {
	reg := `^1([38][0-9]|14[579]|5[^4]|16[6]|7[1-35-8]|9[189])\d{8}$`
	rgx := regexp.MustCompile(reg)
	return rgx.MatchString(mobile)
}

func FormatMobile(s string) string {
	return fmt.Sprintf("%s****%s", s[:3], s[len(s)-4:])
}

func SliceToString(array interface{}) string {
	return strings.Replace(strings.Trim(fmt.Sprint(array), "[]"), " ", ",", -1)
}

// 生成指定位数的随机数字字符串
func GenVerifyCode() string {
	return fmt.Sprintf("%06v", mathRand.New(mathRand.NewSource(time.Now().UnixNano())).Int31n(1000000))
}

// 发短信
func SendMobileMessage(mobiles []string, tplId string, params []string) bool {
	mobileSlice := []string{}
	for _, mobile := range mobiles {
		mobileSlice = append(mobileSlice, fmt.Sprintf("+86%s", mobile))
	}
	appId := beego.AppConfig.String("smsappid")
	secretId := beego.AppConfig.String("secretid")
	secretKey := beego.AppConfig.String("secretkey")
	credential := common.NewCredential(
		secretId,
		secretKey,
	)
	cpf := profile.NewClientProfile()
	client, _ := sms.NewClient(credential, "ap-guangzhou", cpf)
	request := sms.NewSendSmsRequest()
	request.SmsSdkAppid = common.StringPtr(appId)
	request.Sign = common.StringPtr("鲜知校园")
	request.SenderId = common.StringPtr("")
	request.ExtendCode = common.StringPtr("0")
	request.TemplateID = common.StringPtr(tplId)
	request.TemplateParamSet = common.StringPtrs(params)
	request.PhoneNumberSet = common.StringPtrs(mobileSlice)
	response, err := client.SendSms(request)
	if _, ok := err.(*errors.TencentCloudSDKError); ok {
		logs.Error("send mobile message fail:", err)
		return false
	}
	if err != nil {
		logs.Error("send mobile message fail:", err)
		return false
	}
	for _, res := range response.Response.SendStatusSet {
		if *res.Code != "Ok" {
			logs.Error("send mobile message fail:", err)
			return false
		}
	}
	return true
}

func GetAuthorityMap() map[string]bool {
	return map[string]bool{
		"UserAdminControllerShowList":         false,
		"UserAdminControllerDoAdd":            false,
		"UserAdminControllerDoEdit":           false,
		"UserAdminRoleControllerShowList":     false,
		"UserAdminRoleControllerDoAdd":        false,
		"UserAdminRoleControllerDoEdit":       false,
		"AuthorityCategoryControllerShowList": false,
		"AuthorityCategoryControllerDoAdd":    false,
		"AuthorityCategoryControllerDoEdit":   false,
		"AuthorityControllerShowList":         false,
		"AuthorityControllerDoAdd":            false,
		"AuthorityControllerDoEdit":           false,
		"ProvinceControllerShowProvinceList":  false,
		"ProvinceControllerDoAddProvince":     false,
		"ProvinceControllerDoEditProvince":    false,
		"CityControllerShowCityList":          false,
		"CityControllerDoAddCity":             false,
		"CityControllerDoEditCity":            false,
		"ArticleControllerShowList":           false,
		"ArticleControllerDoAdd":              false,
		"ArticleControllerDoEdit":             false,
		"ArticleTypeControllerShowList":       false,
		"ArticleTypeControllerDoAdd":          false,
		"ArticleTypeControllerDoEdit":         false,
		"SchoolControllerShowList":            false,
		"SchoolControllerDoAdd":               false,
		"SchoolControllerDoEdit":              false,
		"UserControllerShowList":              false,
		"UserControllerDoEdit":                false,
		"WechatMenuControllerShowAllList":     false,
		"WechatMenuControllerDoAdd":           false,
		"WechatMenuControllerDoEdit":          false,
		"WechatMenuControllerCreate":          false,
		"WechatReplyControllerShowList":       false,
		"WechatReplyControllerDoAdd":          false,
		"WechatReplyControllerDoEdit":         false,
		"SiteConfigControllerDoEdit":          false,
		"SiteConfigControllerEdit":            false,
		"OrderControllerShowList":             false,
		"PushTimeControllerShowList":          false,
		"PushTimeControllerDoAdd":             false,
		"PushTimeControllerDoEdit":            false,
		"SetMealControllerShowList":           false,
		"SetMealControllerDoAdd":              false,
		"SetMealControllerDoEdit":             false,
	}
}
